package indi.simple.pms.util;

import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.Objects;

/**
 * @Author: wanglunhui
 * @Date: 2021/4/13 22:39
 * @Description:
 */
@Component
@Slf4j
public class SpringUtil implements ApplicationContextAware, DisposableBean {

    private static final String APPLICATION_REPLACE="新ApplicationContext: {}, 原ApplicationContext: {}";
    private static final String APPLICATION_NOT_INJECT="ApplicationContext未注入";
    private static final String APPLICATION_CLEAR="清除ApplicationContext: {}";
    private static ApplicationContext applicationContext = null;

    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        if (SpringUtil.applicationContext != null) {
            log.debug(APPLICATION_REPLACE,applicationContext,SpringUtil.applicationContext);
        }

        SpringUtil.applicationContext = applicationContext;
    }

    public void destroy() {
        clearHolder();
    }

    public static void clearHolder() {
        log.debug(APPLICATION_CLEAR,applicationContext);
        applicationContext = null;
    }

    public static ApplicationContext getApplicationContext() {
        return Objects.requireNonNull(applicationContext,APPLICATION_NOT_INJECT);
    }

    @SuppressWarnings("unchecked")
    public static <T> T getBean(String beanName) {
        return (T) Objects.requireNonNull(applicationContext,APPLICATION_NOT_INJECT).getBean(beanName);
    }

    public static <T> T getBean(String beanName, Class<T> clazz) {
        return Objects.requireNonNull(applicationContext,APPLICATION_NOT_INJECT).getBean(beanName, clazz);
    }

    public static <T> T getBean(Class<T> clazz) {
        return Objects.requireNonNull(applicationContext,APPLICATION_NOT_INJECT).getBean(clazz);
    }

    public static <T> T getBeansOfType(Class<T> clazz) {
        T t = null;
        Map<String, T> map = Objects.requireNonNull(applicationContext,APPLICATION_NOT_INJECT).getBeansOfType(clazz);
        for (Map.Entry<String,T> entry:map.entrySet()){
            t=entry.getValue();
        }

        return t;
    }

    public static boolean containsBean(String beanName) {
        return Objects.requireNonNull(applicationContext,APPLICATION_NOT_INJECT).containsBean(beanName);
    }

    public static boolean isSingleton(String beanName) {
        return Objects.requireNonNull(applicationContext,APPLICATION_NOT_INJECT).isSingleton(beanName);
    }

    public static Class getType(String beanName) {
        return Objects.requireNonNull(applicationContext,APPLICATION_NOT_INJECT).getType(beanName);
    }

    public static String[] getAliases(String name) throws NoSuchBeanDefinitionException {
        return Objects.requireNonNull(applicationContext,APPLICATION_NOT_INJECT).getAliases(name);
    }

    @SuppressWarnings("unchecked")
    public static <T> T getAopProxy(T clazz) {
        return (T)AopContext.currentProxy();
    }

}
